
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       gp_serial_device..c
  * @author     baiyang
  * @date       2021-7-15
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include "gp_serial_device.h"
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
/**
  * @brief       初始化时修改波特率等
  * @param[in]   serial  
  * @param[out]  
  * @retval      
  * @note        
  */
static rt_err_t gp_serial_init(struct rt_device* dev)
{
    rt_err_t ret;

    gp_serial_device_t serial = (gp_serial_device_t)dev;

    struct serial_configure conf = ((struct rt_serial_device *)serial->puart)->config;

    // 根据参数SERIALx_BAUD设置串口波特率
    conf.baud_rate = serial->baud;
    ret = rt_device_control(serial->puart, RT_DEVICE_CTRL_CONFIG, &conf); //修改参数
    return ret;
}

/**
  * @brief       打开对应串口
  * @param[in]   serial  
  * @param[out]  
  * @retval      
  * @note        
  */
static rt_err_t gp_serial_open(struct rt_device* dev, rt_uint16_t oflag)
{
    (void)oflag;

    gp_serial_device_t serial = (gp_serial_device_t)dev;
    dev->open_flag = serial->oflag;
    return rt_device_open(serial->puart, serial->oflag);
}

/**
  * @brief       关闭对应串口
  * @param[in]   serial  
  * @param[out]  
  * @retval      
  * @note        
  */
static rt_err_t gp_serial_close(struct rt_device* dev)
{
    gp_serial_device_t serial = (gp_serial_device_t)dev;
    return rt_device_close(serial->puart);
}

/**
  * @brief       直接从对应串口读数据
  * @param[in]   serial  
  * @param[in]   pos  
  * @param[in]   buffer  
  * @param[in]   size  
  * @param[out]  
  * @retval      
  * @note        
  */
static rt_size_t gp_serial_read(struct rt_device* dev, rt_off_t pos, void* buffer, rt_size_t size)
{
    gp_serial_device_t serial = (gp_serial_device_t)dev;

    SERIAL_ENTER_CRITICAL;
    rt_size_t ret = rt_ringbuffer_get(serial->rb_rx, buffer, size);
    SERIAL_EXIT_CRITICAL;

    return ret;
}

/**
  * @brief       向发送FIFO中存入待发数据
  * @param[in]   serial  
  * @param[in]   pos  
  * @param[in]   buffer  
  * @param[in]   size  
  * @param[out]  
  * @retval      
  * @note        
  */
static rt_size_t gp_serial_write(struct rt_device* dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
    gp_serial_device_t serial = (gp_serial_device_t)dev;

    SERIAL_ENTER_CRITICAL;
    rt_size_t ret = rt_ringbuffer_put(serial->rb_tx, buffer, size); //满时，新数据覆盖旧数据
    SERIAL_EXIT_CRITICAL;

    return ret;
}

/**
  * @brief       控制串口配置参数
  * @param[in]   serial  
  * @param[in]   cmd  
  * @param[in]   arg  
  * @param[out]  
  * @retval      
  * @note        
  */
static rt_err_t gp_serial_control(struct rt_device* dev, int cmd, void* arg)
{
    gp_serial_device_t serial = (gp_serial_device_t)dev;

    if (serial->puart != NULL
        && cmd == RT_DEVICE_CTRL_CONFIG
        && serial->puart->type == RT_Device_Class_Char) {
        serial->baud = ((struct serial_configure *)arg)->baud_rate;
    }

    return rt_device_control(serial->puart, cmd, arg);
}

/**
  * @brief       将各个设备注册
  * @param[in]   serial  
  * @param[in]   name  
  * @param[in]   flag  
  * @param[out]  
  * @retval      
  * @note        
  */
rt_err_t gp_serial_device_register(gp_serial_device_t serial, const char* name, rt_uint32_t flag)
{
    struct rt_device* device;

    RT_ASSERT(serial != RT_NULL);

    device = &(serial->parent);
    device->type        = RT_Device_Class_Char; //是否修改为这个？
    device->ref_count   = 0;
    device->rx_indicate = RT_NULL;
    device->tx_complete = RT_NULL;

    device->init        = gp_serial_init;
    device->open        = gp_serial_open;
    device->close       = gp_serial_close;
    device->read        = gp_serial_read;
    device->write       = gp_serial_write;
    device->control     = gp_serial_control;

    return rt_device_register(device, name, flag);
}

/*------------------------------------test------------------------------------*/


